# -*- coding: utf-8 -*-
import gtk
from kiwi.ui.objectlist import Column, ObjectList
from kiwi.ui.dialogs import yesno
from gtk import RESPONSE_YES
from kiwi.ui.widgets.entry import ProxyEntry, ProxyDateEntry
from kiwi.ui.widgets.checkbutton import ProxyCheckButton
from kiwi.ui.widgets.combo import ProxyComboEntry
from kiwi.ui.widgets.textview import ProxyTextView
from django.db.models.base import ModelBase
from django.db.models import fields, ForeignKey, get_model
from django.db.models.fields.related import ForeignRelatedObjectsDescriptor
import datetime

def func_format(value):
    return value()

def objectlist_from_model(model):
    columns = []
    for i in model._meta.fields:
        if "get_%s_display" % i.name in model.__dict__.keys():
            col = "get_%s_display" % i.name
            ff=func_format
        else:
            col = i.name
            ff=None
        if isinstance(i, fields.BooleanField):
            columns.append(Column(col,
                title=i.verbose_name.title(),
                data_type=bool,
                editable=False,
                format_func=ff,
                radio=True))
        else:
            columns.append(Column(col,
                title=i.verbose_name.title(),
                editable=False,
                format_func=ff))
    list = ObjectList(columns)
    return list

class SlaveEditNew(gtk.VBox):
    def __init__(self, model,
                 list_related=False,
                 list=None,
                 delete_handler=None):
        
        gtk.VBox.__init__(self)
        self.notebook = gtk.Notebook()
        self.pack_start(self.notebook)
        
        self.modelwidgets = {}
        self.model = model
        self.list = list
        self.first_widget = None
        
        
        if model._meta.admin is None:
            self.add_page(model._meta.fields, model._meta.verbose_name.title())
        else:
            if not model._meta.admin.fields is None:
                for i in model._meta.admin.fields:
                    self.add_page([f for f in model._meta.fields if f.name in i[1]['fields']], i[0])
            else:
                self.add_page(model._meta.fields, model._meta.verbose_name.title())
        self.view = None
        self.first_widget
        self.buttonbox = gtk.HButtonBox()
        self.pack_start(self.buttonbox)
        self.buttonbox.set_layout(gtk.BUTTONBOX_END)
        
        self.btnSave = gtk.Button(stock=gtk.STOCK_SAVE)
        self.buttonbox.pack_start(self.btnSave)
        self.btnSave.connect('clicked', self.on_btnSave_clicked)
        
        self.btnSaveNew = gtk.Button(label="Save and add new")
        self.buttonbox.pack_start(self.btnSaveNew)
        self.btnSaveNew.connect('clicked', self.on_btnSaveNew_clicked)
        
        self.btnClose = gtk.Button(stock=gtk.STOCK_CLOSE)
        self.buttonbox.pack_start(self.btnClose)
        if delete_handler is None:
            self.btnClose.connect('clicked', self.on_btnClose_clicked)
            self.delete_handler = self.on_btnClose_clicked
        else:
            self.btnClose.connect('clicked', delete_handler)
            self.delete_handler = delete_handler
        
        if list_related:
            self.list_related()
        self.first_widget.grab_focus()
    
    def save(self):
        for i in self.modelwidgets:
            if type(self.modelwidgets[i]) is ProxyComboEntry:
                self.model.__setattr__(i, self.modelwidgets[i].read())
            else:
                value = self.modelwidgets[i].read()

                if i != "id":
                    self.model.__setattr__(i, value)
        self.model.validate()
        self.model.save()
        if self.list is None:
            return
        try:
            self.list.update(self.model)
        except:
            self.list.append(self.model)
    
    def on_btnSave_clicked(self, btn=None):
        self.save()
        self.delete_handler()
    
    def on_btnSaveNew_clicked(self, btn=None):
        self.save()
        self.model = get_model(self.model._meta.app_label,
                               self.model._meta.object_name)()
        for i in self.modelwidgets:
            if type(self.modelwidgets[i]) is ProxyComboEntry:
                self.modelwidgets[i].update(None)
            else:
                self.modelwidgets[i].update(self.modelwidgets[i].data_type())
        self.first_widget.grab_focus()
    
    def on_btnClose_clicked(self, btn=None):
        self.hide()
        self.destroy()

    def add_page(self, fields_list, title):
        self.table = gtk.Table(len(fields_list)+1, 2)
        self.notebook.append_page(self.table, gtk.Label(title))
        x = 0
        for i in fields_list:
            sw = None
            if isinstance(i, ForeignKey) or len(i._get_choices())>0:
                entry = ProxyComboEntry()
                entry.data_type = long
                choices = [(c[1], c[0]) for c in i.get_choices() if c[0] != '']
                entry.prefill(choices)
                self.modelwidgets['%s_id' % i.name] = entry
                sw = gtk.HBox()
                #ugly
                try:
                    if self.model.__getattribute__("%s_id" % i.name ) is not None:
                        entry.select_item_by_data(self.model.__getattribute__("%s_id" % i.name))
                except:
                    if self.model.__getattribute__("%s" % i.name ) is not None:
                        entry.select_item_by_data(self.model.__getattribute__("%s" % i.name))
                sw.pack_start(entry,True, True)
                button = gtk.Button()
                image = gtk.Image()
                image.set_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_MENU)
                image.show()
                button.add(image)
                button.set_relief(gtk.RELIEF_NONE)
                sw.pack_start(button, False, False)
            else:
                entry = ProxyEntry()
                if isinstance(i, fields.TextField):
                    sw = gtk.ScrolledWindow()
                    sw.set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS)
                    entry = ProxyTextView()
                    entry.data_type = unicode
                    sw.add(entry)
                elif isinstance(i, fields.CharField):
                    entry.data_type = unicode
                elif isinstance(i, fields.FloatField):
                    entry.data_type = float
                elif isinstance(i, fields.AutoField):
                    entry.data_type = long
                elif isinstance(i, fields.IntegerField):
                    entry.data_type = int
                if isinstance(i, fields.DateField):
                    entry = ProxyDateEntry()
                    if type(self.model.__getattribute__(i.name)) is not datetime.date:
                        self.model.__setattr__(i.name, datetime.date.today())
                elif isinstance(i, fields.BooleanField):
                    entry = ProxyCheckButton()
                    if type(self.model.__getattribute__(i.name)) is not bool:
                        self.model.__setattr__(i.name, False)
                self.modelwidgets['%s' % i.name] = entry
                if i.name == "id":
                    entry.set_sensitive(False)
                if self.model.__getattribute__(i.name) is not None:
                    entry.update(self.model.__getattribute__(i.name))


            label = gtk.Label(i.verbose_name.title() + ":")
            label.set_alignment(0, 0)
            if self.first_widget is None:
                self.first_widget = entry
            self.table.attach(label,
                         0, 1, x, x+1, yoptions=gtk.FILL,xoptions=gtk.FILL)
            if sw is None:
                self.table.attach(entry,1 ,2 , x, x+1, yoptions=gtk.FILL,
                        xoptions=gtk.FILL|gtk.EXPAND)
            else:
                self.table.attach(sw,1 ,2 , x, x+1, yoptions=gtk.FILL,
                        xoptions=gtk.FILL|gtk.EXPAND)
            x += 1
        self.notebook.set_current_page(0)    
    
    def list_related(self):
        
        for i in dir(model):
            if '_set' in i and not i.startswith("_"):
                v = ModelForm(model.__getattribute__(i).model, model.__getattribute__(i).select_related())
                self.append_page(v, gtk.Label(model.__getattribute__(i).model._meta.verbose_name.title()))
        self.notebook.set_current_page(0)

class ModelForm(gtk.VBox):

    def __init__(self, model, objects=None, list_related=False):
        self.model = model
        gtk.VBox.__init__(self)
        ui = '''<ui>
        <toolbar name="Toolbar">
          <toolitem action="Add"/>
          <toolitem action="Remove"/>
          <toolitem action="Properties"/>
          <toolitem action="Close"/>
        </toolbar>
        </ui>'''
        
        # Create a UIManager instance
        self.uimanager = gtk.UIManager()
    
        # Create an ActionGroup
        self.actiongroup = gtk.ActionGroup('UIManager')
        
        
        # Create actions
        self.actiongroup.add_actions([('Add', gtk.STOCK_ADD, None, None,
                                  None, self.add_cb),
                                 ('Remove', gtk.STOCK_REMOVE, None, None,
                                  None, self.remove_cb),
                                 ('Properties', gtk.STOCK_PROPERTIES, None, None,
                                  None, self.edit_cb),
                                 ('Close', gtk.STOCK_CLOSE, None, None,
                                  None, self.close_cb)])
        # Add the actiongroup to the uimanager
        self.uimanager.insert_action_group(self.actiongroup, 0)
    
        # Add a UI description
        self.uimanager.add_ui_from_string(ui)
    
        # Create a Toolbar
        self.toolbar = self.uimanager.get_widget('/Toolbar')
        self.toolbar.set_style(gtk.TOOLBAR_ICONS)
        self.toolbar.set_icon_size(gtk.ICON_SIZE_MENU)
        
        self.pack_start(self.toolbar, False, False)
        self.vp = gtk.VPaned()
        self.pack_start(self.vp)
        self.list = objectlist_from_model(model)
        if objects is None:
            self.list.extend(model.objects.all())
        else:
            self.list.extend(objects)
        self.list.connect('row-activated', self.list_row_activated)
        self.vp.add1(self.list)
        self.show_all()
        
    def add_cb(self, action):
        self.edit_model(self.model())
    
    def list_row_activated(self, list, model):
        self.edit_model(model)

    def edit_cb(self, action):
        model = self.list.get_selected()
        self.edit_model(model)
        
    def close_cb(self, action):
        if type(self.parent) is gtk.Window:
            gtk.main_quit()
        elif type(self.parent) is gtk.Notebook:
            self.parent.remove_page(self.parent.get_current_page())
        
    def remove_cb(self, action):
        model = self.list.get_selected()
        resp = yesno(u'You are going to delete %s, ¿Are You sure?' % model)
        if resp == RESPONSE_YES:
            self.list.remove(model)
            model.delete()
    
    def edit_model(self, model):

        self.view = gtk.Dialog(model._meta.verbose_name.title(),
                     self.parent.get_toplevel(),
                     gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
        self.view.set_default_size(600, 300)
        self.view.set_has_separator(False)
        self.slave = SlaveEditNew(model,
                list=self.list,
                delete_handler=self.on_Cancel__clicked)

        self.view.vbox.add(self.slave)
        self.view.show_all()

    def on_Cancel__clicked(self, btn=None, arg=None):
        self.view.hide()
        self.view.destroy()


def get_module_list(module):
    list = ObjectList(Column("_meta.verbose_name.title", "Module", editable=False, format_func=func_format))
    for i in dir(module):
        if type(module.__getattribute__(i)) is ModelBase:
            list.append(module.__getattribute__(i))
    return list

class ApplicationForm(gtk.Window):
    
    def __init__(self, models_module, title="App"):
        gtk.Window.__init__(self)
        self.set_title(title)
        vbox = gtk.VBox()
        self.add(vbox)
        hp = gtk.HPaned()
        
        vbox.pack_start(hp)
        self.list = get_module_list(models_module)
        self.list.connect("row-activated", self.on_list_clicked)
        f = gtk.Frame()
        f.set_shadow_type(gtk.SHADOW_IN)
        f.add(self.list)
        hp.pack1(f, True, True)
        self.ntb = gtk.Notebook()
        hp.pack2 (self.ntb, False, True)
        hp.set_position(300)
        self.connect('delete-event', gtk.main_quit)
        self.show_all()
        
    def on_list_clicked(self, list, model):
        l = gtk.Label('')
        l.set_text_with_mnemonic(model._meta.verbose_name.title())
        widget = ModelForm(model)
        self.ntb.append_page(widget, l)
        widget.show()
        self.ntb.set_current_page(-1)
